home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / WINGs / wsplitview.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-11-07  |  18.5 KB  |  872 lines

  1.  
  2.  
  3.  
  4.  
  5. #include "WINGsP.h"
  6.  
  7. /*
  8. char *WMSplitViewDidResizeSubviewsNotification
  9.     = "WMSplitViewDidResizeSubviewsNotification";
  10. char *WMSplitViewWillResizeSubviewsNotification
  11.     = "WMSplitViewWillResizeSubviewsNotification";
  12. */
  13.  
  14. typedef struct _T_SplitViewSubview {
  15.     WMView *view;
  16.     int minSize;
  17.     int maxSize;
  18.     int size;
  19.     int pos;
  20. } T_SplitViewSubview;
  21.  
  22.  
  23. typedef struct W_SplitView {
  24.     W_Class widgetClass;
  25.     W_View *view;
  26.     
  27.     WMBag *subviewsBag;
  28.     
  29.     WMSplitViewConstrainProc *constrainProc;
  30.     
  31.     struct {
  32.     unsigned int vertical:1;    
  33.     unsigned int adjustOnPaint:1;
  34.     unsigned int subviewsWereManuallyMoved:1;
  35.     } flags;
  36.  
  37.     /* WMSplitViewResizeSubviewsProc *resizeSubviewsProc; */
  38.  
  39. } SplitView;
  40.  
  41.  
  42. #define DIVIDER_THICKNESS   8
  43. #define MIN_SUBVIEW_SIZE    4
  44. #define MAX_SUBVIEW_SIZE    -1
  45.  
  46.  
  47. #define _GetSubviewsCount() WMGetBagItemCount(sPtr->subviewsBag)
  48.  
  49. #define _AddPSubviewStruct(P) \
  50. (WMPutInBag(sPtr->subviewsBag,((void*)P)))
  51.  
  52. #define _GetPSubviewStructAt(i) \
  53. ((T_SplitViewSubview*)WMGetFromBag(sPtr->subviewsBag,(i)))
  54.  
  55. #define _GetSubviewAt(i) \
  56. (((T_SplitViewSubview*)WMGetFromBag(sPtr->subviewsBag,(i)))->view)
  57.  
  58. #define _GetMinSizeAt(i) \
  59. (((T_SplitViewSubview*)WMGetFromBag(sPtr->subviewsBag,(i)))->minSize)
  60.  
  61. #define _GetMaxSizeAt(i) \
  62. (((T_SplitViewSubview*)WMGetFromBag(sPtr->subviewsBag,(i)))->maxSize)
  63.  
  64. #define _GetSizeAt(i) \
  65. (((T_SplitViewSubview*)WMGetFromBag(sPtr->subviewsBag,(i)))->size)
  66.  
  67. #define _GetPosAt(i) \
  68. (((T_SplitViewSubview*)WMGetFromBag(sPtr->subviewsBag,(i)))->pos)
  69.  
  70. #define _GetSplitViewSize() \
  71. ((sPtr->flags.vertical) ? sPtr->view->size.width : sPtr->view->size.height)
  72.  
  73. static void destroySplitView(SplitView *sPtr);
  74. static void paintSplitView(SplitView *sPtr);
  75.  
  76. static void handleEvents(XEvent *event, void *data);
  77. static void handleActionEvents(XEvent *event, void *data);
  78.  
  79.  
  80. static void
  81. getConstraints(SplitView *sPtr, int index, int *minSize, int *maxSize)
  82. {
  83.     *minSize = MIN_SUBVIEW_SIZE;
  84.     *maxSize = MAX_SUBVIEW_SIZE;
  85.  
  86.     if (sPtr->constrainProc)
  87.     (*sPtr->constrainProc)(sPtr, index, minSize, maxSize);
  88.  
  89.     if (*minSize < MIN_SUBVIEW_SIZE)
  90.     *minSize = MIN_SUBVIEW_SIZE;
  91.  
  92.     if (*maxSize < MIN_SUBVIEW_SIZE)
  93.         *maxSize = MAX_SUBVIEW_SIZE;
  94.     else if (*maxSize < *minSize)
  95.         *maxSize = *minSize;
  96. }
  97.  
  98.  
  99. static void
  100. updateConstraints(SplitView *sPtr)
  101. {
  102.     T_SplitViewSubview *p;
  103.     int i, count;
  104.  
  105.     count = _GetSubviewsCount();
  106.     for (i = 0; i < count; i++) {
  107.         p = _GetPSubviewStructAt(i);
  108.         getConstraints(sPtr, i, &(p->minSize), &(p->maxSize));
  109.     }
  110. }
  111.  
  112.  
  113. static void
  114. resizeView(SplitView *sPtr, WMView *view, int size)
  115. {
  116.     int width, height;
  117.  
  118.     if (sPtr->flags.vertical) {
  119.     width = size;
  120.         height = sPtr->view->size.height;
  121.     } else {
  122.     width = sPtr->view->size.width;
  123.         height = size;
  124.     }
  125.  
  126.     if (view->self)
  127.     WMResizeWidget(view->self, width, height);
  128.     else
  129.     W_ResizeView(view, width, height);
  130. }
  131.  
  132.  
  133. static void
  134. reparentView(SplitView *sPtr, WMView *view, int pos)
  135. {
  136.     int x, y;
  137.  
  138.     if (sPtr->flags.vertical) {
  139.         x = pos;
  140.     y = 0;
  141.     } else {
  142.         x = 0;
  143.     y = pos;
  144.     }
  145.  
  146.     W_ReparentView(view, sPtr->view, x, y);
  147. }
  148.  
  149.  
  150. static void
  151. moveView(SplitView *sPtr, WMView *view, int pos)
  152. {
  153.     int x, y;
  154.  
  155.     if (sPtr->flags.vertical) {
  156.         x = pos;
  157.     y = 0;
  158.     } else {
  159.         x = 0;
  160.     y = pos;
  161.     }
  162.  
  163.     if (view->self)
  164.     WMMoveWidget(view->self, x, y);
  165.     else
  166.     W_MoveView(view, x, y);
  167. }
  168.  
  169.  
  170. static int
  171. checkSizes(SplitView *sPtr)
  172. {
  173.     int i, count, offset;
  174.     T_SplitViewSubview *p;
  175.  
  176.     count = _GetSubviewsCount();
  177.     offset = 0;
  178.     for (i = 0; i < count; i++) {
  179.         p = _GetPSubviewStructAt(i);
  180.     if (p->size < p->minSize) {
  181.         offset += p->minSize - p->size;
  182.         p->size = p->minSize;
  183.     } else if (p->maxSize != MAX_SUBVIEW_SIZE && p->size > p->maxSize) {
  184.         offset += p->maxSize - p->size;
  185.         p->size = p->maxSize;
  186.     }
  187.     }
  188.     
  189.     return (offset);
  190. }
  191.  
  192.  
  193. static void
  194. checkPositions(SplitView *sPtr)
  195. {
  196.     int i, count, pos;
  197.     T_SplitViewSubview *p;
  198.  
  199.     count = _GetSubviewsCount();
  200.     pos = 0;
  201.     for (i = 0; i < count; i++) {
  202.         p = _GetPSubviewStructAt(i);
  203.     p->pos = pos;
  204.     pos += p->size + DIVIDER_THICKNESS;
  205.     }
  206. }
  207.  
  208.  
  209. static void
  210. updateSubviewsGeom(SplitView *sPtr)
  211. {
  212.     int i, count;
  213.     T_SplitViewSubview *p;
  214.  
  215.     count = _GetSubviewsCount();
  216.     for (i = 0; i < count; i++) {
  217.         p = _GetPSubviewStructAt(i);
  218.     resizeView(sPtr, p->view, p->size);
  219.     moveView(sPtr, p->view, p->pos);
  220.     }
  221. }
  222.  
  223.  
  224. static int
  225. getTotalSize(SplitView *sPtr)
  226. {
  227.     int i, count, totSize;
  228.  
  229.     count = _GetSubviewsCount();
  230.     if (!count)
  231.         return (0);
  232.  
  233.     totSize = 0;
  234.     for (i = 0; i < count; i++)
  235.         totSize += _GetSizeAt(i) + DIVIDER_THICKNESS;
  236.     
  237.     return (totSize - DIVIDER_THICKNESS);
  238. }
  239.  
  240.  
  241. static Bool
  242. distributeOffsetEqually(SplitView *sPtr, int offset)
  243. {
  244.     T_SplitViewSubview *p;
  245.     int i, count, sizeChanged, forced;
  246.  
  247.     if ((count = _GetSubviewsCount()) < 1)
  248.         return (True);
  249.  
  250.     forced = False;
  251.     while (offset != 0) {
  252.     sizeChanged = 0;
  253.         for (i = 0; i < count && offset != 0; i++) {
  254.             p = _GetPSubviewStructAt(i);
  255.         if (offset < 0) {
  256.             if (p->size > p->minSize) {
  257.             offset++;
  258.                 p->size--;
  259.             sizeChanged = 1;
  260.         }
  261.         } else if (p->maxSize == MAX_SUBVIEW_SIZE || p->size < p->maxSize) {
  262.         offset--;
  263.             p->size++;
  264.         sizeChanged = 1;
  265.         }
  266.         }
  267.     if (offset != 0 && !sizeChanged) {
  268.         p = _GetPSubviewStructAt(count-1);
  269.         if (offset > 0) {
  270.             p->size += offset;
  271.             p->maxSize = MAX_SUBVIEW_SIZE;
  272.         }
  273.         offset = 0;
  274.         forced = True;
  275.     }
  276.     }
  277.     
  278.     return (forced);
  279. }
  280.  
  281.  
  282. static Bool
  283. distributeOffsetFormEnd(SplitView *sPtr, int offset)
  284. {
  285.     T_SplitViewSubview *p;
  286.     int i, count, sizeTmp;
  287.  
  288.     if ((count = _GetSubviewsCount()) < 1)
  289.         return (True);
  290.  
  291.     for (i = count-1; i >= 0 && offset != 0; i--) {
  292.     p = _GetPSubviewStructAt(i);
  293.     sizeTmp = p->size;
  294.     if (offset > 0) {
  295.         if (p->maxSize == MAX_SUBVIEW_SIZE || p->size + offset < p->maxSize)
  296.             p->size += offset;
  297.         else
  298.         p->size = p->maxSize;
  299.     } else {
  300.         if (p->size + offset >= p->minSize)
  301.             p->size += offset;
  302.         else
  303.         p->size = p->minSize;
  304.     }
  305.     offset -= p->size - sizeTmp;
  306.     }
  307.  
  308.     return (offset == 0);
  309. }
  310.  
  311.  
  312. static void
  313. adjustSplitViewSubviews(WMSplitView *sPtr)
  314. {
  315.     T_SplitViewSubview *p;
  316.     int i, count, adjSize, adjPad;
  317.  
  318.     CHECK_CLASS(sPtr, WC_SplitView);
  319.  
  320. #if 0
  321.     printf("---- (adjustSplitViewSubviews - 1) ----\n");
  322.     dumpSubviews(sPtr);
  323. #endif
  324.  
  325.     if ((count = _GetSubviewsCount()) < 1)
  326.     return;
  327.  
  328.     adjSize = (_GetSplitViewSize() - ((count-1) * DIVIDER_THICKNESS))  / count;
  329.     adjPad =  (_GetSplitViewSize() - ((count-1) * DIVIDER_THICKNESS)) % count;
  330.     for (i = 0; i < count; i++) {
  331.         p = _GetPSubviewStructAt(i);
  332.     p->size = adjSize;
  333.     }
  334.     
  335.     distributeOffsetEqually(sPtr, adjPad - checkSizes(sPtr));
  336.     
  337.     checkPositions(sPtr);
  338.     updateSubviewsGeom(sPtr);
  339.     
  340.     sPtr->flags.subviewsWereManuallyMoved = 0;
  341.  
  342. #if 0    
  343.     printf("---- (adjustSplitViewSubviews - 2) ----\n");
  344.     dumpSubviews(sPtr);
  345. #endif
  346. }
  347.  
  348. #if 0
  349. static void
  350. handleSubviewResized(void *self, WMNotification *notif)
  351. {
  352.     SplitView *sPtr = (SplitView*)self;
  353.  
  354.     CHECK_CLASS(sPtr, WC_SplitView);
  355.  
  356.     if (WMGetNotificationName(notif) == WMViewSizeDidChangeNotification) {
  357.         T_SplitViewSubview *p;
  358.         int i, count, done;
  359.         WMView *view = WMGetNotificationObject(notif);
  360.  
  361.         count = _GetSubviewsCount();
  362.         done = 0;
  363.     for (i = 0; i < count; i++) {
  364.             p = _GetPSubviewStructAt(i);
  365.         if (p->view == view) {
  366.             done = 1;
  367.         break;
  368.         }
  369.     }
  370.     
  371.     if (done) {
  372.         /* TODO !!! */
  373.         resizeView(sPtr, p->view, p->size);
  374.         moveView(sPtr, p->view, p->pos);
  375.     }
  376.     }
  377. }
  378. #endif
  379.  
  380. static void
  381. handleViewResized(void *self, WMNotification *notification)
  382. {
  383.     SplitView *sPtr = (SplitView*)self;
  384.  
  385. #if 0
  386.     printf("---- (handleViewResized - 1) ----\n");
  387.     dumpSubviews(sPtr);
  388. #endif
  389.  
  390.     updateConstraints(sPtr);
  391.     checkSizes(sPtr);
  392.     
  393.     if (sPtr->constrainProc || sPtr->flags.subviewsWereManuallyMoved) {
  394.         distributeOffsetFormEnd(sPtr, _GetSplitViewSize() - getTotalSize(sPtr));
  395.         checkPositions(sPtr);
  396.         updateSubviewsGeom(sPtr);
  397.     } else
  398.         adjustSplitViewSubviews(sPtr);
  399.  
  400.     assert(checkSizes(sPtr) == 0);
  401.  
  402. #if 0
  403.     printf("---- (handleViewResized - 2) ----\n");
  404.     dumpSubviews(sPtr);
  405. #endif
  406. }
  407.  
  408.  
  409. static void
  410. paintSplitView(SplitView *sPtr)
  411. {
  412.     T_SplitViewSubview *p;
  413.     W_Screen *scr = sPtr->view->screen;
  414.     int x, y, i, count;
  415.     WMPixmap *dimple = scr->scrollerDimple;
  416.  
  417. #if 0
  418.     printf("---- (paintSplitView - 1) ----\n");
  419.     dumpSubviews(sPtr);
  420. #endif
  421.     
  422.     if (!sPtr->view->flags.mapped || !sPtr->view->flags.realized)
  423.         return;
  424.  
  425.     XClearWindow(scr->display, sPtr->view->window);
  426.  
  427.     count = _GetSubviewsCount();
  428.     if (count == 0)
  429.         return;
  430.  
  431.     if (sPtr->flags.adjustOnPaint) {
  432.     handleViewResized(sPtr, NULL);
  433.     sPtr->flags.adjustOnPaint = 0;
  434.     }
  435.  
  436.     XSetClipMask(scr->display, scr->clipGC, dimple->mask);
  437.  
  438.     if (sPtr->flags.vertical) {
  439.     x = ((DIVIDER_THICKNESS - dimple->width) / 2);
  440.     y = (sPtr->view->size.height - dimple->height)/2;
  441.     } else {
  442.     x = (sPtr->view->size.width - dimple->width)/2;
  443.     y = ((DIVIDER_THICKNESS - dimple->height) / 2);
  444.     }
  445.  
  446.     for (i = 0; i < count-1; i++) {
  447.         p = _GetPSubviewStructAt(i);
  448.  
  449.     if (sPtr->flags.vertical)
  450.             x += p->size;
  451.     else
  452.             y += p->size;
  453.  
  454.     XSetClipOrigin(scr->display, scr->clipGC, x, y);
  455.     XCopyArea(scr->display, dimple->pixmap, sPtr->view->window,
  456.           scr->clipGC, 0, 0, dimple->width, dimple->height, x, y);
  457.     
  458.     if (sPtr->flags.vertical)
  459.             x += DIVIDER_THICKNESS;
  460.     else
  461.         y += DIVIDER_THICKNESS;
  462.     }
  463.  
  464. #if 0
  465.     printf("---- (paintSplitView - 2) ----\n");
  466.     dumpSubviews(sPtr);
  467. #endif
  468. }
  469.  
  470.  
  471. static void
  472. drawDragingRectangle(SplitView *sPtr, int pos)
  473. {
  474.     int x, y, w, h;
  475.     
  476.     if (sPtr->flags.vertical) {
  477.         x = pos;
  478.     y = 0;
  479.     w = DIVIDER_THICKNESS;
  480.     h = sPtr->view->size.height;
  481.     } else {
  482.         x = 0;
  483.     y = pos;
  484.     w = sPtr->view->size.width;
  485.     h = DIVIDER_THICKNESS;
  486.     }
  487.     
  488.     XFillRectangle(sPtr->view->screen->display, sPtr->view->window,
  489.            sPtr->view->screen->ixorGC, x, y, w, h);
  490. }
  491.  
  492.  
  493. static void
  494. getMinMaxDividerCoord(SplitView *sPtr, int divider, int *minC, int *maxC)
  495. {
  496.     int relMinC, relMaxC;
  497.     int totSize = _GetSizeAt(divider) + _GetSizeAt(divider+1);
  498.  
  499.     relMinC = _GetMinSizeAt(divider);
  500.     if (_GetMaxSizeAt(divider+1) != MAX_SUBVIEW_SIZE
  501.      && relMinC < totSize - _GetMaxSizeAt(divider+1))
  502.         relMinC = totSize - _GetMaxSizeAt(divider+1);
  503.  
  504.     relMaxC = totSize - _GetMinSizeAt(divider+1);
  505.     if (_GetMaxSizeAt(divider) != MAX_SUBVIEW_SIZE
  506.      && relMaxC > _GetMaxSizeAt(divider))
  507.         relMaxC = _GetMaxSizeAt(divider);
  508.     
  509.     *minC = _GetPosAt(divider) + relMinC;
  510.     *maxC = _GetPosAt(divider) + relMaxC;
  511. }
  512.  
  513.  
  514. static void
  515. dragDivider(SplitView *sPtr, int clickX, int clickY)
  516. {
  517.     int divider, pos, ofs, done, dragging;
  518.     int i, count;
  519.     XEvent ev;
  520.     WMScreen *scr;
  521.     int minCoord, maxCoord, coord;
  522.  
  523.     if (sPtr->constrainProc) {
  524.     updateConstraints(sPtr);
  525.     checkSizes(sPtr);
  526.     distributeOffsetFormEnd(sPtr, _GetSplitViewSize() - getTotalSize(sPtr));
  527.     checkPositions(sPtr);
  528.     updateSubviewsGeom(sPtr);
  529.     }
  530.  
  531.     scr = sPtr->view->screen;
  532.     divider = ofs = pos = done = 0;
  533.     coord = (sPtr->flags.vertical) ? clickX : clickY;
  534.     count = _GetSubviewsCount();
  535.     if (count < 2)
  536.         return;
  537.  
  538.     for (i = 0; i < count-1; i++) {
  539.     pos += _GetSizeAt(i) + DIVIDER_THICKNESS;
  540.     if (coord < pos) {
  541.         ofs = coord - pos + DIVIDER_THICKNESS;
  542.         done = 1;
  543.         break;
  544.     }
  545.     divider++;
  546.     }
  547.  
  548.     if (!done)
  549.         return;
  550.  
  551.     getMinMaxDividerCoord(sPtr, divider, &minCoord, &maxCoord);
  552.  
  553.     done = 0;
  554.     dragging = 0;
  555.     while (!done) {
  556.     WMMaskEvent(scr->display, ButtonMotionMask|ButtonReleaseMask
  557.             |ExposureMask, &ev);
  558.  
  559.         coord = (sPtr->flags.vertical) ? ev.xmotion.x : ev.xmotion.y;
  560.  
  561.     switch (ev.type) {
  562.      case ButtonRelease:
  563.         done = 1;
  564.         if (dragging)
  565.         drawDragingRectangle(sPtr, pos);
  566.         break;
  567.         
  568.      case MotionNotify:
  569.         if (dragging)
  570.         drawDragingRectangle(sPtr, pos);
  571.         if (coord - ofs < minCoord)
  572.         pos = minCoord;
  573.         else if (coord - ofs > maxCoord)
  574.         pos = maxCoord;
  575.         else
  576.         pos = coord - ofs;
  577.         drawDragingRectangle(sPtr, pos);
  578.         dragging = 1;
  579.         break;
  580.         
  581.      default:
  582.         WMHandleEvent(&ev);
  583.         break;
  584.     }
  585.     }
  586.     
  587.     if (dragging) {
  588.         T_SplitViewSubview *p1, *p2;
  589.     int totSize;
  590.     
  591.     p1 = _GetPSubviewStructAt(divider);
  592.     p2 = _GetPSubviewStructAt(divider+1);
  593.     
  594.     totSize = p1->size + DIVIDER_THICKNESS + p2->size;
  595.     
  596.     p1->size = pos - p1->pos;
  597.     p2->size = totSize - p1->size - DIVIDER_THICKNESS;
  598.     p2->pos = p1->pos + p1->size  + DIVIDER_THICKNESS;
  599.     
  600.     resizeView(sPtr, p1->view, p1->size);
  601.     moveView(sPtr, p2->view, p2->pos);
  602.     resizeView(sPtr, p2->view, p2->size);
  603.     sPtr->flags.subviewsWereManuallyMoved = 1;
  604.     }
  605. }
  606.  
  607.  
  608. static void
  609. handleEvents(XEvent *event, void *data)
  610. {
  611.     SplitView *sPtr = (SplitView*)data;
  612.  
  613.     CHECK_CLASS(data, WC_SplitView);
  614.  
  615.  
  616.     switch (event->type) {    
  617.      case Expose:
  618.     if (event->xexpose.count!=0)
  619.         break;
  620.     paintSplitView(sPtr);
  621.     break;
  622.     
  623.      case DestroyNotify:
  624.     destroySplitView(sPtr);
  625.     break;
  626.     }
  627. }
  628.  
  629.  
  630. static void
  631. handleActionEvents(XEvent *event, void *data)
  632. {
  633.     
  634.     CHECK_CLASS(data, WC_SplitView);
  635.  
  636.     switch (event->type) {
  637.      case ButtonPress:
  638.     if (event->xbutton.button == Button1)
  639.         dragDivider(data, event->xbutton.x, event->xbutton.y);
  640.     break;
  641.     }
  642. }
  643.  
  644.  
  645.  
  646. static void
  647. destroySplitView(SplitView *sPtr)
  648. {
  649.     int i, count;
  650.  
  651.     count = _GetSubviewsCount();
  652.     for (i = 0; i < count; i++)
  653.         wfree(WMGetFromBag(sPtr->subviewsBag, i));
  654.     WMFreeBag(sPtr->subviewsBag);
  655.    
  656.     WMRemoveNotificationObserver(sPtr);
  657.     
  658.     wfree(sPtr);
  659. }
  660.  
  661. WMSplitView*
  662. WMCreateSplitView(WMWidget *parent)
  663. {
  664.     SplitView *sPtr;
  665.  
  666.     sPtr = wmalloc(sizeof(SplitView));
  667.     memset(sPtr, 0, sizeof(SplitView));
  668.  
  669.     sPtr->widgetClass = WC_SplitView;
  670.     
  671.     sPtr->view = W_CreateView(W_VIEW(parent));
  672.     if (!sPtr->view) {
  673.     wfree(sPtr);
  674.     return NULL;
  675.     }
  676.     sPtr->view->self = sPtr;
  677.  
  678.     WMSetViewNotifySizeChanges(sPtr->view, True);
  679.  
  680.     WMCreateEventHandler(sPtr->view, ExposureMask|StructureNotifyMask
  681.              |ClientMessageMask, handleEvents, sPtr);
  682.  
  683.  
  684.     WMCreateEventHandler(sPtr->view, ButtonPressMask|ButtonReleaseMask
  685.              |EnterWindowMask|LeaveWindowMask, 
  686.              handleActionEvents, sPtr);
  687.  
  688.     
  689.     WMAddNotificationObserver(handleViewResized, sPtr, 
  690.                   WMViewSizeDidChangeNotification, sPtr->view);
  691.     
  692.     sPtr->subviewsBag = WMCreateBag(8);
  693.  
  694.     return sPtr;
  695. }
  696.  
  697.  
  698. void
  699. WMAdjustSplitViewSubviews(WMSplitView *sPtr)
  700. {
  701.     CHECK_CLASS(sPtr, WC_SplitView);
  702.     
  703.     checkSizes(sPtr);
  704.  
  705.     adjustSplitViewSubviews(sPtr);
  706.  
  707.     assert(checkSizes(sPtr) == 0);
  708. }
  709.  
  710.  
  711. void
  712. WMAddSplitViewSubview(WMSplitView *sPtr, WMView *subview)
  713. {
  714.     int wasMapped, count;
  715.     T_SplitViewSubview *p;
  716.  
  717.     CHECK_CLASS(sPtr, WC_SplitView);
  718.  
  719.     if (!(p = (T_SplitViewSubview*)wmalloc(sizeof(T_SplitViewSubview))))
  720.         return;
  721.  
  722.     wasMapped = subview->flags.mapped;
  723.     if (wasMapped)
  724.     W_UnmapView(subview);
  725.  
  726.     count = _GetSubviewsCount();
  727.     p->view = subview;
  728.     getConstraints(sPtr, count, &(p->minSize), &(p->maxSize));
  729.     if (sPtr->flags.vertical)
  730.         p->size = subview->size.width;
  731.     else
  732.         p->size = subview->size.height;
  733.  
  734.     WMPutInBag(sPtr->subviewsBag,(void*)p);
  735.     reparentView(sPtr, subview, 0);
  736.     
  737. /*
  738.     We should have something like that...
  739.     
  740.     WMSetViewNotifySizeChanges(subview, True);
  741.     WMAddNotificationObserver(handleSubviewResized, sPtr, 
  742.                   WMViewSizeDidChangeNotification,
  743.                   subview);
  744.     WMSetViewNotifyMoveChanges(subview, True);
  745.     WMAddNotificationObserver(handleSubviewResized, sPtr, 
  746.                   WMViewMoveDidChangeNotification,
  747.                   subview);
  748. */
  749.     if (wasMapped)
  750.     W_MapView(subview);
  751.     
  752.     sPtr->flags.adjustOnPaint = 1;
  753.     paintSplitView(sPtr);
  754. }
  755.  
  756.  
  757. WMView*
  758. WMGetSplitViewSubviewAt(WMSplitView *sPtr, int index)
  759. {
  760.     CHECK_CLASS(sPtr, WC_SplitView);
  761.  
  762.     if (index > 0 && index < _GetSubviewsCount())
  763.         return (_GetSubviewAt(index));
  764.     else
  765.         return (NULL);
  766. }
  767.  
  768.  
  769. void
  770. WMRemoveSplitViewSubview(WMSplitView *sPtr, WMView *view)
  771. {
  772.     T_SplitViewSubview *p;
  773.     int i, count;
  774.  
  775.     CHECK_CLASS(sPtr, WC_SplitView);
  776.  
  777.     count = _GetSubviewsCount();
  778.     for (i = 0; i < count; i++) {
  779.         p = _GetPSubviewStructAt(i);
  780.     if (p->view == view) {
  781.             wfree(p);
  782.             WMDeleteFromBag(sPtr->subviewsBag, i);
  783.             sPtr->flags.adjustOnPaint = 1;
  784.             paintSplitView(sPtr);
  785.         break;
  786.     }
  787.     }
  788. }
  789.  
  790.  
  791. void
  792. WMRemoveSplitViewSubviewAt(WMSplitView *sPtr, int index)
  793. {
  794.     T_SplitViewSubview *p;
  795.  
  796.     CHECK_CLASS(sPtr, WC_SplitView);
  797.  
  798.     if (index > 0 && index < _GetSubviewsCount()) {
  799.         p = _GetPSubviewStructAt(index);
  800.         wfree(p);
  801.         WMDeleteFromBag(sPtr->subviewsBag, index);
  802.         sPtr->flags.adjustOnPaint = 1;
  803.     paintSplitView(sPtr);
  804.     }
  805. }
  806.  
  807.  
  808. void 
  809. WMSetSplitViewConstrainProc(WMSplitView *sPtr, WMSplitViewConstrainProc *proc)
  810. {
  811.     CHECK_CLASS(sPtr, WC_SplitView);
  812.  
  813.     sPtr->constrainProc = proc;
  814. }
  815.  
  816.  
  817. int
  818. WMGetSplitViewSubviewsCount(WMSplitView *sPtr)
  819. {
  820.     CHECK_CLASS(sPtr, WC_SplitView);
  821.  
  822.     return (_GetSubviewsCount());
  823. }
  824.  
  825.  
  826. Bool
  827. WMGetSplitViewVertical(WMSplitView *sPtr)
  828. {
  829.     CHECK_CLASS(sPtr, WC_SplitView);
  830.  
  831.     return (sPtr->flags.vertical == 1);
  832. }
  833.  
  834. void
  835. WMSetSplitViewVertical(WMSplitView *sPtr, Bool flag)
  836. {
  837.     int vertical;
  838.     
  839.     CHECK_CLASS(sPtr, WC_SplitView);
  840.  
  841.     vertical = (flag) ? 1 : 0;
  842.     if (sPtr->flags.vertical == vertical)
  843.         return;
  844.     
  845.     sPtr->flags.vertical = vertical;
  846.     
  847.     if (sPtr->view->flags.mapped && sPtr->view->flags.realized)
  848.         handleViewResized(sPtr, NULL);
  849.     else
  850.         sPtr->flags.adjustOnPaint = 1;
  851. }
  852.  
  853.  
  854. int
  855. WMGetSplitViewDividerThickness(WMSplitView *sPtr)
  856. {
  857.     CHECK_CLASS(sPtr, WC_SplitView);
  858.  
  859.     return (DIVIDER_THICKNESS);
  860. }
  861.  
  862. #if 0
  863. void
  864. WMSetSplitViewResizeSubviewsProc(WMSplitView *sPtr, 
  865.                  WMSplitViewResizeSubviewsProc *proc)
  866. {
  867.     CHECK_CLASS(sPtr, WC_SplitView);
  868.  
  869.     sPtr->resizeSubviewsProc = proc;
  870. }
  871. #endif
  872.